using MediatR;
using WeatherMcpServer.Data.Entities;
using WeatherMcpServer.Data.Repositories;

namespace WeatherMcpServer.Application.Alerts.Commands;

/// <summary>
/// 评估实时天气数据并根据规则触发预警。
/// </summary>
public record EvaluateWeatherDataCommand(
    string? RegionCode,
    string? RegionName,
    double? TemperatureMax,
    double? TemperatureMin,
    double? RainMm,
    double? WindLevel,
    WeatherType? TypeHint
) : IRequest<IReadOnlyList<long>>;

public class EvaluateWeatherDataHandler : IRequestHandler<EvaluateWeatherDataCommand, IReadOnlyList<long>>
{
    private readonly IWeatherRuleRepository _ruleRepo;
    private readonly IMediator _mediator;

    public EvaluateWeatherDataHandler(IWeatherRuleRepository ruleRepo, IMediator mediator)
    {
        _ruleRepo = ruleRepo;
        _mediator = mediator;
    }

    public async Task<IReadOnlyList<long>> Handle(EvaluateWeatherDataCommand request, CancellationToken cancellationToken)
    {
        var alerts = new List<long>();
        // 加载启用的规则（可按 RegionCode 与 TypeHint 过滤）
        var rules = await _ruleRepo.GetEnabledRulesAsync(request.TypeHint, request.RegionCode, cancellationToken);

        foreach (var rule in rules)
        {
            if (IsMatch(rule, request))
            {
                // 将规则映射到预警严重性与类型
                var id = await _mediator.Send(new CreateWeatherAlertCommand(
                    Type: rule.Type,
                    Severity: rule.Severity,
                    RegionCode: request.RegionCode,
                    RegionName: request.RegionName,
                    TemperatureMax: request.TemperatureMax,
                    TemperatureMin: request.TemperatureMin,
                    RainMm: request.RainMm,
                    WindLevel: request.WindLevel,
                    Message: rule.Description
                ), cancellationToken);
                alerts.Add(id);
            }
        }
        return alerts;
    }

    private static bool IsMatch(WeatherRule rule, EvaluateWeatherDataCommand data)
    {
        // 根据类型选择指标：这里示例以温度/降雨/风力三类为主
        double? metric = rule.Type switch
        {
            WeatherType.HighTemperature => data.TemperatureMax,
            WeatherType.LowTemperature => data.TemperatureMin,
            WeatherType.HeavyRain => data.RainMm,
            WeatherType.Wind => data.WindLevel,
            _ => null
        };

        if (metric is null && rule.ConditionType != RuleConditionType.Between && rule.ConditionType != RuleConditionType.Equal)
            return false;

        return rule.ConditionType switch
        {
            RuleConditionType.GreaterOrEqual => metric.HasValue && rule.Threshold1.HasValue && metric.Value >= rule.Threshold1.Value,
            RuleConditionType.LessOrEqual => metric.HasValue && rule.Threshold1.HasValue && metric.Value <= rule.Threshold1.Value,
            RuleConditionType.Equal => metric.HasValue && rule.Threshold1.HasValue && Math.Abs(metric.Value - rule.Threshold1.Value) < 1e-6,
            RuleConditionType.Between => metric.HasValue && rule.Threshold1.HasValue && rule.Threshold2.HasValue &&
                                         metric.Value >= Math.Min(rule.Threshold1.Value, rule.Threshold2.Value) &&
                                         metric.Value <= Math.Max(rule.Threshold1.Value, rule.Threshold2.Value),
            _ => false
        };
    }
}
